<?PHP
class HttpService
{
  private $rules;

  public function __construct($rules)
  {
	 $this->rules = $rules;
  }

  public function restoreState()
  {
	 $context = Aurora\Session::get();
	 
	 $context->restore($_REQUEST, $_SESSION, $_COOKIE);
  }

  public function undefinedModule($moduleName, $methodName)
  {
	 return new ErrorResult(sprintf("Page %s in Module %s not found", $methodName, $moduleName));
  }
  
  public function outputFile($file)
  {
	 $mimeType = mime_content_type2($file);
	 //header("Content-Description: File Transfer");
	 header("Content-Type: $mimeType");
	 //header('Content-Disposition: attachment; filename='.basename($file));
	 header("Expires: 0");
	 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
	 header("Pragma: public");
	 header("Content-Length: " . filesize($file));
	 
	 readfile($file);
  }

  public function dispatch()
  {
	  global $appRoot;
	 $pathInfo = ltrim($_SERVER['PATH_INFO'], "/\\");
	   $fileName = realpath(implode(DIRECTORY_SEPARATOR, array($appRoot, $pathInfo)));
	 if (file_exists($fileName))
	 {
		  $this->outputFile($fileName);
		   return;
	   }
	 list($moduleName, $methodName) = explode("/", $pathInfo . "/");

	 $moduleTypeName = isset($this->rules[$moduleName]) ? $this->rules[$moduleName] : reset($this->rules);
	 $methodName = empty($methodName) ? "index" : $methodName;

	 $moduleType = new \ReflectionEx\ClassInfo($moduleTypeName);
	 if (!$moduleType->hasMethod($methodName))
	 {
		$result = $this->undefinedModule($moduleName, $methodName);

		$result->show();

		return;
	 }

	 $module = $moduleType->newInstance();
	 $methodInfo = $moduleType->getMethod($methodName);
	 $args = $this->buildMethodArgsFromRequest($methodInfo, $_REQUEST);
	 $result = $methodInfo->invokeArgs($module, $args);

	 $result->show();
  }

  /**
   * @param \ReflectionMethod $methodInfo
   * @param array $request
   * @return array
   */
  public function buildMethodArgsFromRequest($methodInfo, $request)
  {
	 $args = array();
	 $params = $methodInfo->getParameters();
	 $roleName = $methodInfo->getAttribute("role");
	 foreach ($params as $i => $p)
	 {
		$parameterName = $p->getName();
		$typeInfo = $p->getClass();
		if (array_key_exists($parameterName, $request))
		{
		   $args[] = $_REQUEST[$parameterName];
		}
		elseif (!empty($typeInfo))
		{
		   if ($typeInfo->hasMethod("fillFromArray"))
		   {
			  $inst = $typeInfo->newInstance();
			  $inst->fillFromArray($request);
			  $args[] = $inst;
		   }
		}
	 }

	 return $args;
  }

  public function dispatchError()
  {
	 $type = new ReflectionClass($this);
  
	 header("HTTP/1.1 500 Internal Server Error");
	 header("Content-Type: text/plain");

	 printf("Unimplemented service: %s", $type->getName());
  }
}
